package utils;

import models.TA001;
import models.TA014;
import org.dom4j.*;
import play.cache.Cache;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by xuyang on 2018/1/11.
 */
public class TemplateMatcher {

    public static List<TA014> matchedTemplatesForACARS(TA001 acars) {
        List<TA014> templates = TA014.filterBy(null, acars.getAircraft_id(), acars.getSmi(), null, -1);

        return templates;
    }

    public static List<TA014> guessMatchedTemplateForACARS(TA001 acars) {
        List<TA014> result = new ArrayList<>();


        List<TA014> splitTemplates;
        List cache = (List) Cache.get("SplitTemplates");
        if (cache == null) {
            splitTemplates = TA014.findAll();
            Cache.add("SplitTemplates", splitTemplates);
        } else {
            splitTemplates = cache;
        }

        // 根据marker猜测模版，并根据marker长度设置rank
        final int rankOfCode2 = 5;
        final int rankOfSMI = 5;
        String code2 = acars.getFlight_id().substring(0,2);
        String smi = acars.getSmi();

        for (TA014 tmpl: splitTemplates) {
            tmpl.rank = 0;

            if (isMarkerMatched(tmpl.marker, tmpl.marker_pos, acars.getFreeText())) {
                tmpl.rank = tmpl.marker.length();

                // 根据执行的航班两字码和smi匹配度打分，各算5分
                if (tmpl.split_template_name.contains(code2)) {
                    tmpl.rank += rankOfCode2;
                }
                if (tmpl.smi.equals(smi)) {
                    tmpl.rank += rankOfSMI;
                }

                result.add(tmpl);
            }
        }

        // 根据rank排序（倒序）
        result.sort((o1, o2) -> -Integer.compare(o1.rank, o2.rank));

        int top = 0;
        List<TA014> topResult = new ArrayList<>();
        for (TA014 o: result) {
            if (top <= o.rank) {
                top = o.rank;

                try {
                    Object r = templateSplitResultFor(o.template, acars.getFreeText());
                    if (r == null) {
                        o.rank = 0;
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    o.rank = 0;
                }

                topResult.add(o);
            } else {
                break;
            }
        }

        return topResult;
    }

    public static boolean isMarkerMatched(String marker, String marker_pos, String msgBody) {

        if (marker.equalsIgnoreCase("NONE")) {
            return true;
        }

        try {
            String[] tokens = marker_pos.split("\\(|\\)|,");

            String type = tokens[0];

            String[] lines = msgBody.replace("\r\n", "\n").split("\n");

            int row = Integer.valueOf(tokens[1]);
            if (row > lines.length) {
                return false;
            }

            if (type.equals("1")) {
                // 绝对位置
                int col = Integer.valueOf(tokens[2]);

                String actualMarker = lines[row - 1].substring(col - 1, col - 1 + marker.length());
                if (actualMarker.equals(marker)) {
                    return true;
                }
            } else if (type.equals("2")) {
                if (lines[0].contains(marker)) {
                    return true;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

        return false;
    }

    public static Element templateSplitResultFor(String template, String msgBody) throws DocumentException {
        // 加一个哨兵位
        msgBody += "\n&#x3;";
        msgBody = msgBody.replace("\r\n", "\n");
        Element dataElem = DocumentFactory.getInstance().createElement("data");

        template = template.replace("&", "&amp;");
        Document document = DocumentHelper.parseText(template);
        List parameters = document.selectNodes("//parameters/parameter");

        int curPos = 0;
        for (Object p: parameters) {
            Element parameter = (Element)p;

            String name = parameter.selectSingleNode("name").getText();
            String uniformName = parameter.selectSingleNode("uniformName").getText();
            String length = parameter.selectSingleNode("length").getText();
            String prefix = parameter.selectSingleNode("prefix").getText();
            String postfix = parameter.selectSingleNode("postfix").getText();
            String format = parameter.selectSingleNode("format").getText();
            String description = parameter.selectSingleNode("description").getText();
            String index = parameter.selectSingleNode("index").getText();


            byte flag = 0;
            if (prefix!=null && !prefix.isEmpty()) flag |= (1<<2);
            if (length!=null && !length.isEmpty() && !length.trim().equals("0")) flag |= (1<<1);
            if (postfix!=null && !postfix.isEmpty()) flag |= 1;

            String item = null;

            switch(flag) {
                case 1: // 0 0 1   只有postfix有效
                    int end = msgBody.indexOf(postfix, curPos);
                    if (end == -1) return null;

                    item = msgBody.substring(curPos, end);
                    curPos = end;
                    break;
                case 2: // 0 1 0   只有length有效
                    int l = Integer.valueOf(length);
                    if (l + curPos > msgBody.length()) return null;

                    item = msgBody.substring(curPos, curPos + l);
                    curPos = curPos + l;
                    break;
                case 3: // 0 1 1   只有length和postfix有效
                    l = Integer.valueOf(length);
                    end = msgBody.indexOf(postfix, curPos);
                    int start = end - l;
                    start = start<curPos? curPos:start;
                    item = msgBody.substring(start, end);
                    curPos = end;
                    break;
                case 4: // 1 0 0   只有prefix有效，无法拆分
                    break;
                case 5: // 1 0 1   只有prefix和postfix有效
                    start = msgBody.indexOf(prefix, curPos);
                    if (start == -1) return null;
                    start += prefix.length();
                    end = msgBody.indexOf(postfix, start);
                    if (end == -1) return  null;
                    item = msgBody.substring(start, end);
                    curPos = end;
                    break;
                case 6: // 1 1 0   只有prefix和length有效
                    start = msgBody.indexOf(prefix, curPos);
                    if (start == -1) return null;
                    start += prefix.length();
                    l = Integer.valueOf(length);
                    end = start + l;
                    item = msgBody.substring(start, end);
                    curPos = end;
                    break;
                case 7: // 1 1 1   全部参数齐全，可进行长度判断
                    start = msgBody.indexOf(prefix, curPos);
                    if (start == -1) return null;
                    start += prefix.length();
                    end = msgBody.indexOf(postfix, start);
                    if (end == -1) return  null;
                    l = Integer.valueOf(length);

                    // 进行长度判断(不做）
                    // if (end - start != l) return null;
                    item = msgBody.substring(start, end);
                    curPos = end;
                    break;
                default:
                    break;
            }

            if (item == null) continue;

            Element unitElem = dataElem.addElement("unit");
            unitElem.addElement("index").setText(index);
            unitElem.addElement("uniformName").setText(uniformName);
            unitElem.addElement("value").setText(item);
            unitElem.addElement("format").setText(format);
            unitElem.addElement("name").setText(name);
        }

        return dataElem;
    }
}
